﻿using System;
using System.Collections.Generic;
using CoreVirtuoso.Config;
using CoreVirtuoso.Descriptions;
using Infrastructure.Entities;
using Infrastructure.Events.Interfaces;
using Infrastructure.Helpers;
using NGenerics.DataStructures;
using VirtuosoDal.Repositories.RdfRepositories.Events;

namespace Infrastructure.Events
{
    public class EventsOntologyClassesService : IEventsOntologyClassesService
    {
        private readonly IEventsOntologyClassesTreeBuilder _eventsOntologyClassesTreeBuilder;

        private static readonly Dictionary<LanguageSpecificUri, GeneralTree<EntityDescription>> _classesTreesCache;

        static EventsOntologyClassesService()
        {
            _classesTreesCache = new Dictionary<LanguageSpecificUri, GeneralTree<EntityDescription>>();
        }

        public EventsOntologyClassesService(IEventsOntologyClassesTreeBuilder eventsOntologyClassesTreeBuilder)
        {
            _eventsOntologyClassesTreeBuilder = eventsOntologyClassesTreeBuilder;
        }

        public GeneralTree<EntityDescription> GetClassesTree(string rootClassUri, string language)
        {
            LanguageSpecificUri languageSpecificUri = new LanguageSpecificUri(rootClassUri, language);

            if (!_classesTreesCache.ContainsKey(languageSpecificUri))
            {
                EventsOntologyRepository eventsOntologyRepository = new EventsOntologyRepository();

                _classesTreesCache[languageSpecificUri] = _eventsOntologyClassesTreeBuilder.GetClassesTree(rootClassUri, language);
            }

            return _classesTreesCache[languageSpecificUri];
        }

        //ToDo: Move to IClassNodeSearcher
        private GeneralTree<EntityDescription> GetClassNode(GeneralTree<EntityDescription> classesTree, string classUri)
      {
            GeneralTree<EntityDescription> classNode = classesTree.FindNode(ed => ed.Uri.OriginalString == classUri);
         if (classNode != null)
            return classNode;

         return null;
      }

        public string GetClassLabel(string rootClassUri, string classUri, string language)
        {
            GeneralTree<EntityDescription> classesTree = GetClassesTree(rootClassUri, language);

            GeneralTree<EntityDescription> classNode = GetClassNode(classesTree, classUri);

            if (classNode == null)
                return null;

            return classNode.Data.Label;
        }

        public string GetEventTypeHierarchyString(string eventTypeUri, string language)
        {
            GeneralTree<EntityDescription> classesTree = GetClassesTree(EventsOntologyUris.EventClassUri, language);

            return GetEventTypeHierarchyStringInternally(classesTree, eventTypeUri, "");
        }

        //ToDo: Move to IEventClassHierarchyBuilder
        private string GetEventTypeHierarchyStringInternally(GeneralTree<EntityDescription> classesTree, string childEventTypeUri, string hierarchyString)
        {
            GeneralTree<EntityDescription> classNode = GetClassNode(classesTree, childEventTypeUri);
            if (classNode == null)
                return null; // it is not a use case; it means that initial childEventTypeUri is outside of hierarchy

            if (classNode.Parent.Data.Uri.OriginalString == classesTree.Data.Uri.OriginalString)
                return classNode.Data.Label + hierarchyString;

            hierarchyString = String.Format(" &rarr; {0}", classNode.Data.Label) + hierarchyString;
            return GetEventTypeHierarchyStringInternally(classNode, classNode.Parent.Data.Uri.OriginalString, hierarchyString);
        }
    }
}
